/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
*/

package com.jinhe.tss.core.cachepool.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.jinhe.tss.core.cachepool.Cacheable;
import com.jinhe.tss.core.cachepool.IPool;
import com.jinhe.tss.core.cachepool.TimeWrapper;
import com.jinhe.tss.core.cachepool.strategy.CacheConstants;

/**
 * <p>
 * Disabler.java
 * </p>
 * 用动态代理来管理缓存池的缓存策略停用/启用两种状态下存取数据操作的差异。
 * </p><p>
 * 加入了一个mixin功能，扩展了缓存池的动态代理类的功能，</p><p>
 * 其可以直接停用/启用，而不要调用Cachestrategy.setDisabled()。
 * </p><p>
 * 通过调用本动态代理类，用户可以不去设置IPool接口的</p><p>
 * 各个实现类的getObject，putObject，check-out,check-in操作相应的关于停用/启用的处理。</p><p>
 * 
 * @author Jon.King 2006-8-13
 */
public class Disabler{
    
    public static Object disableWrapper(final Object object) {
        /* 
         * 对ThreadPool不进行拦截，因为需要对它进行向下强制转换类型，代理后就不能转换了。if(object instanceof ThreadPool) return object;
         * 改进：ThreadPool已实现了IThreadPool接口，动态代理后可以自由转换为IThreadPool接口，上诉的问题不复存在 */
        
        // IPool的实现类都有一个抽象的父类
        Class<?>[] interfaces = ProxyUtil.getInterfaces(object.getClass()); 
        
        if(object instanceof IPool){
            Class<?>[] temp = new Class[interfaces.length + 1];
            for(int i = 0; i < interfaces.length; i++){
                temp[i] = interfaces[i];
            }
            temp[temp.length - 1] = IDisable.class;  //将mixin的IDisable的接口也加进来
            interfaces = temp;
        }

        return Proxy.newProxyInstance(object.getClass().getClassLoader(), interfaces, new InvocationHandler(){
            
            Object target = object;

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if(target instanceof IPool){
                    /* 如果调用方法是属于IDisable的，则将目标对象切换new DisableMixin()；*/
                    IPool pool = (IPool)target;
                    if(method.getDeclaringClass().equals(IDisable.class)){
                        target = new DisableMixin(pool);
                    }
                    
                    /* 
                     * 如果缓存策略已经关闭: 
                     * 取数据时则不从池中获取而重新加载数据；
                     * 存数据则不将数据放到缓存池中，直接返回null 
                     */
                    if(CacheConstants.TRUE.equals(pool.getCacheStrategy().getDisabled())){
                        //不进行初始化
                        if (method.getName().equals("init")) 
                            return null;
                        
                        //如果是调用getObject方法则调用载入器重新载入。参数args[0]为key值
                        if (method.getName().equals("getObject"))          
                            return pool.reload(new TimeWrapper(args[0], null)); 
                        
                        if (method.getName().equals("putObject"))
                            return null; 
                        
                        //如果是调用checkOut 方法则调用池算法器创建一个
                        if (method.getName().equals("checkOut"))          
                            return pool.getArithmetic().create(pool.getCacheStrategy().getCyclelife()); 

                        if (method.getName().equals("checkIn")){
                            pool.getArithmetic().destroy((Cacheable) args[0]);
                            return null; 
                        }
                    }
                }
                
                try {
                    return method.invoke(target, args);
                } catch (InvocationTargetException e) {
                    throw e.getTargetException();
                }
            }
        });
    }
}
